package com.njtoyo.taxi.admin.logic.business.driver;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.cache.SecondaryCachePutter;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverSpecialRewardLog;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverSpecialRewardRule;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverRewardCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverSpecialRewardRuleCategory;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverSpecialRewardRuleType;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverMapper;
import com.njtoyo.taxi.admin.mapper.master.mapper.GeoDriverRegionMapper;
import com.njtoyo.taxi.admin.rest.presenter.business.driver.DriverCantonCompanyVo;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.GeoRegionIdAndCantonIdVo;
import com.njtoyo.taxi.admin.rest.wrapper.business.driver.GiveDriverSpecialRewardWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toSet;

@Service
public class DriverSpecialRewardRuleLogic {
    @Autowired
    private SecondaryCachePutter secondaryCachePutter;

    @Autowired
    private PrimaryCachePutter primaryCachePutter;

    @Autowired
    private GeoDriverRegionMapper geoDriverRegionMapper;

    @Autowired
    private DriverSpecialRewardLogLogic driverSpecialRewardLogLogic;

    @Autowired
    private DriverMapper driverMapper;

    // 随机时间发放大额红包奖励
    public void randomTimeGiveSpecialReward(DriverSpecialRewardRule rule, Integer periodCount) throws Exception {
        // 校验
        if (!DriverSpecialRewardRuleCategory.recommend_red_packet.equals(rule.getCategory())) {
            throw new Exception("该规则奖励类型不是大额红包奖励");
        }

        if (!DriverSpecialRewardRuleType.random_time.equals(rule.getRuleType())) {
            throw new Exception("当前奖励规则不是随机时间类型");
        }

        // 判断当日是否已发放
        if (secondaryCachePutter.hasDriverSpecialRewardRule(rule.getId())) {
            throw new Exception("今日已经随机抽取过了");
        }

        // 随机时间
        Date start = convertTime(rule.getRewardDistributeStartHm());
        Date end = convertTime(rule.getRewardDistributeEndHm());

        long totalTime = DateUtil.between(start, end, DateUnit.SECOND) - 10 * 60;

        double step = Math.floor(NumberUtil.div(totalTime, periodCount.longValue()));

        int intStep = (int) step;

        // 根据司机运营区ids批量获取cantonId
        GeoRegionIdAndCantonIdVo geoRegionIdAndCantonIdVo = geoDriverRegionMapper.convertDriverRegionIdToCantonId(rule.getDriverRegionId());

        List<DriverSpecialRewardLog> batchInsert = new ArrayList<>();

        for (int i = 0; i < periodCount; i++) {
            DriverSpecialRewardLog log = new DriverSpecialRewardLog();
            log.setDriverRegionId(rule.getDriverRegionId());
            log.setCantonId(geoRegionIdAndCantonIdVo.getCantonId());
            log.setRewardCategory(DriverRewardCategory.redPacket);
            log.setRewardAmount(rule.getRewardAmount());
            log.setRewardDistributeEnd(end);

            log.setRewardDistributeStart(RandomUtil.randomDate(start, DateField.SECOND, 1, intStep));

            batchInsert.add(log);

            // 递增start
            start = DateUtil.offsetSecond(start, intStep);
        }

        // 入库
        driverSpecialRewardLogLogic.saveBatch(batchInsert);

        // 清除缓存
        primaryCachePutter.clearDriverSpecialReward(DateUtil.beginOfDay(new Date()).getTime());

        // 标记当日已经随机抽取过了
        secondaryCachePutter.addDriverSpecialRewardRule(rule.getId(), batchInsert);
    }

    public void giveDriverSpecialReward(List<GiveDriverSpecialRewardWrapper.GiveDriverSpecialRewardDto> rewardDetail) throws Exception {
        Set<Long> driverIds = rewardDetail.stream().map(GiveDriverSpecialRewardWrapper.GiveDriverSpecialRewardDto::getDrivers)
                .collect(toSet())
                .stream().flatMap(Collection::stream)
                .collect(toSet());

        // 批量查司机信息
        List<DriverCantonCompanyVo> driverList = driverMapper.selectDriverCantonCompanyList(driverIds);
        if (ObjectUtil.isEmpty(driverList) || driverList.size() != driverIds.size()) {
            throw new Exception("操作失败，司机信息有误");
        }

        Map<Long, DriverCantonCompanyVo> driverMap = driverList.stream().collect(Collectors.toMap(DriverCantonCompanyVo::getDriverId, i -> i));

        // 获取司机cantonIds
        Set<Long> cantonIds = driverList.stream().map(DriverCantonCompanyVo::getCantonId).collect(toSet());
        List<GeoRegionIdAndCantonIdVo> cantonToDriverRegionList = geoDriverRegionMapper.convertDriverCantonIdsToRegionId(cantonIds);

        if (ObjectUtil.isEmpty(driverList)) {
            throw new Exception("操作失败，司机信息有误");
        }
        Map<Long, Long> cantonToDriverRegionMap = cantonToDriverRegionList.stream().collect(Collectors.toMap(GeoRegionIdAndCantonIdVo::getCantonId, GeoRegionIdAndCantonIdVo::getDriverRegionId));

        List<DriverSpecialRewardLog> batchInsert = new ArrayList<>();
        Date today = DateUtil.beginOfDay(new Date());

        rewardDetail.forEach(i -> {
            DriverSpecialRewardLog log = new DriverSpecialRewardLog();
            log.setRewardCategory(DriverRewardCategory.redPacket);
            log.setRewardDistributeStart(DateUtil.offsetHour(today, 9));
            log.setRewardDistributeEnd(DateUtil.endOfDay(today).setField(DateField.MILLISECOND, 0));
            // 未领取
            log.setIsReceived(false);

            i.getDrivers().forEach(driver -> {
                DriverCantonCompanyVo driverVo = driverMap.get(driver);

                if (Objects.nonNull(driverVo)) {
                    log.setCantonId(driverVo.getCantonId());
                    log.setCompanyId(driverVo.getCompanyId());
                    log.setDriverRegionId(cantonToDriverRegionMap.get(driverVo.getCantonId()));
                }

                log.setRewardAmount(i.getAmount());
                log.setDriverId(driver);

                batchInsert.add(log);
            });
        });

        // 2、插入数据
        driverSpecialRewardLogLogic.saveBatch(batchInsert);

        // 3、清除缓存
        primaryCachePutter.clearDriverSpecialReward(today.getTime());
    }

    public Date convertTime(String hm) {
        Date today = DateUtil.beginOfDay(new Date());

        String hour = hm.substring(0, 2);
        String minute = hm.substring(2);

        int intHour = Integer.parseInt(hour);
        int intMinute = Integer.parseInt(minute);

        DateTime convertHour = DateUtil.offsetHour(today, intHour);

        return DateUtil.offsetMinute(convertHour, intMinute);
    }

}
